/*
 * Copyright (C) 2012-2013 Matthias Zeimer and the miniframes project group.
 * All rights reserved. 
 * 
 * Licensed under the Eclipse Public License, Version 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.opensource.org/licenses/EPL-1.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package de.miniframes.minivalues;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.Date;
import java.util.Formatter;
import java.util.IllegalFormatException;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.UUID;

/**
 * <p>
 * A value is something unmodifiable. Here: A value is an {@link Object} with an
 * unmodifiable state.
 * </p>
 * 
 * <h4><a name="intention">Intention</a></h4>
 * <p>
 * The idea behind this class is a simplified method to declare side-effect free
 * types, called: values. By the fact that a value will never change its state,
 * you can distribute and share it over multiple {@link Thread}s. Some classes
 * in the Java programming language were designed like this before; for example
 * the class {@link String}.
 * <p>
 * 
 * <p>
 * Custom value types may used to underline the meaning of a concrete raw-value
 * in a simple type like {@code int} or {@code String}. A custom value type does
 * much better communicate the intention of the value, adds a possibility to
 * simply document the values kind and avoids code redundancies in range or
 * format checks.
 * </p>
 * 
 * <p>
 * Instances of two subclasses, {@link DomainValue} and {@link TechnicalValue},
 * are used to indicate the motivation for the concrete value type, which is
 * domain specific or a technical purpose. This class is not intended to be
 * inherited immediately (see <a href="#literature1">[1]</a>).
 * </p>
 * 
 * <p>
 * The use of custom value types enhance the readability and understandability
 * of a project if this concept is used consequently.
 * </p>
 * 
 * 
 * 
 * <h4><a name="immediatelysupportedfeatures">Immediately supported features</a>
 * </h4>
 * <p>
 * Using this framework will guarantees the unmodifyableness and some rules
 * listed below of any sub-class of this class using an approximate test case
 * (see {@link ValueVerifier}) and some pre-defined implemenations. It provides
 * a simplified way to declare custom value types and offers some basic features
 * like equality check, stable string representation and pre-implemented
 * comparability.
 * </p>
 * 
 * <p>
 * This class provides a definition of {@link Object#equals(Object)} and
 * {@link Object#hashCode()} which results based on the values properties passes
 * to {@link #Value(String, Object...)}. Please notice the note on
 * {@link #equals(Object)} for the equality definition of values.
 * </p>
 * 
 * <p>
 * A {@link #toString()} method is provided to return the result of
 * {@link String#format(java.util.Locale, String, Object...)} using the passed
 * format string in {@link #Value(String, Object...)} and the {@link Locale} set
 * to {@code null} (no localisation to guarantee a stable result in any
 * environment).
 * </p>
 * 
 * <h4><a name="classrules">Value class rules</a></h4>
 * <p>
 * Generic value class rules for <em>all</em> value classes:
 * <ul>
 * <li>all fields <em>must</em> fit the value class <a href="#fieldrules">field
 * rules</a> (see below),</li>
 * <li>the class <em>must not</em> be a {@linkplain Class#isMemberClass() member
 * class},</li>
 * <li>the class <em>must not</em> be {@linkplain Class#isAnonymousClass()
 * anonymous} (which would be a member class),</li>
 * <li>all values' properties <em>must</em> be passed to
 * {@link #Value(String, Object...)}.
 * </ul>
 * 
 * </p>
 * 
 * <p>
 * The <em>concrete value class</em>, a sub class of DomainValue, TechnicalValue
 * or an abstract value class <em>must</em> satisfy all of the following rules
 * in addition to the generic value class rules:
 * <ul>
 * <li>the class which is assigned to the type parameter {@code T} <em>must</em>
 * be the concrete value class itself (auto-reflexive declaration),</li>
 * <li>all constructors <em>must</em> be {@linkplain Modifier#PRIVATE private}
 * (please refer the <a href="#recommendations">recommendations</a>),</li>
 * <li>the class <em>must</em> be declared as {@linkplain Modifier#FINAL final}.
 * </li>
 * </ul>
 * </p>
 * 
 * <p>
 * An <em>abstract value class</em> as abstraction over different very similar
 * values, which is also a sub class of DomainValue, TechnicalValue or an
 * abstract value class and could be inherited by a concrete value class (see
 * above), <em>must</em> satisfy all of the following rules in addition to the
 * generic value class rules:
 * <ul>
 * <li>the class which is assigned to the type parameter {@code T} <em>must</em>
 * be the concrete value subclass by this the abstract class <em>must</em> pass
 * the concrete type with an own type argument,</li>
 * <li>all constructors <em>must</em> be {@linkplain Modifier#PROTECTED
 * protected} or package private (please refer the <a
 * href="#recommendations">recommendations</a>),</li>
 * <li>the class <em>must</em> be declared as {@linkplain Modifier#ABSTRACT
 * abstract}.</li>
 * </ul>
 * </p>
 * 
 * <h4><a name="fieldrules">Field rules</a></h4>
 * <p>
 * Generic field rules:
 * <ul>
 * <li>all fields <em>must</em> be declared as {@linkplain Modifier#FINAL final}
 * ,</li>
 * <li>all fields <em>must not</em> be declared as
 * {@linkplain Modifier#TRANSIENT transient},</li>
 * <li>all fields <em>should</em> be declared as {@linkplain Modifier#PRIVATE
 * private} or {@linkplain Modifier#PROTECTED protected}.</li>
 * </ul>
 * </p>
 * 
 * <p>
 * Field type rules: Any value defines its state with and only with other values
 * or value-like types. Theses types are:
 * <ul>
 * <li>all Java primitives (using their Java primitive wrappers used for
 * auto-boxing) (see <a href="#literature2">[2]</a> and <a
 * href="#literature3">[3]</a>),</li>
 * <li>other values (any subclasses of this class)</li>
 * <li>an {@link UnmodifiableTimestamp},</li>
 * <li>an {@link UnmodifiableArray} of a type {@code T} that <em>must</em>
 * satisfy the <a href="#classrules">value class rules</a> or a type that
 * <em>must</em> satisfy the this field type rules,</li>
 * <li>an {@link Enum} for which all its declared fields <em>must</em> satisfy
 * these value class <a href="#fieldrules">field rules (like
 * {@link RoundingMode})</a>,</li>
 * <li>The JavaSE-types {@link String}, {@link BigInteger}, {@link BigDecimal},
 * {@link MathContext} and {@link UUID}.</li>
 * </ul>
 * Other types are <em>not</em> permitted.
 * </p>
 * 
 * <p>
 * <em>Note:</em> {@linkplain Field#isSynthetic() Synthetic fields} are ignored.
 * </p>
 * 
 * <h4><a name="recommendations">Recommendations</a></h4>
 * <p>
 * Caused by the <a href="#classrules">value class rules</a> a value class has
 * no public constructor, you need to use a factory method. This method
 * <em>must</em> check all restriction and throw an approximate
 * {@link Exception} in case of invalid arguments. The naming for this factory
 * method may relay on project specific recommendations, the default name is
 * {@code valueOf}. There are no restrictions for the factory methods
 * visibility.
 * </p>
 * 
 * <p>
 * Let {@code InvoiceNumber} be a value type then you may use a factory method
 * like:
 * 
 * <pre>
 * public static InvoiceNumber valueOf(int numberAsInt) 
 *         throws IllegalArgumentException
 * {
 *     // Check constraints here:
 *     if( !(numberAsInt > 0) )
 *     {
 *         throw new IllegalArgumentException("numberAsInt MUST be > 0.");
 *     }
 * 
 *     // Now "initiate" the value with the previously approved data:
 *     return new InvoiceNumber(numberAsInt);
 * }
 * </pre>
 * 
 * The call would look like:
 * 
 * <pre>
 * InvoiceNumber myNumber = InvoiceNumber.valueOf( 42 );
 * </pre>
 * 
 * The use of a factory method like shown here communicate well that
 * {@code InvoiceNumber} is value type instead of a modifiable object type.
 * </p>
 * 
 * <p>
 * A value class constructor would <em>only initialise</em> the fields (if
 * declared) <em>and</em> pass the previous approved value properties to its
 * super class. The proof of restrictions for the values properties and all
 * required pre-calculations <em>should</em> be done in a factory-method as
 * described above. There <em>must</em> be only one constructor beside the
 * default constructor.
 * </p>
 * 
 * <p>
 * A formal recommendation: We say &quot;a value is selected&quot; instead of
 * &quot;a value is created&quot; so we do not call a value an instance.
 * </p>
 * 
 * <h4><a name="examples">Examples</a></h4>
 * <p>
 * See examples in <a href="./package-summary.html">packages documentation</a>.
 * </p>
 * 
 * <h4><a name="literature">Literature</a></h4>
 * <dl>
 * <dt><a name="literature1">[1]</a></dt>
 * <dd>
 * &quot;Auf der Suche nach Werten in der Softwaretechnik: Werte und Objekte in
 * objektorientierten Programmiersprachen&quot;, J&ouml;rg Rathlev, Beate
 * Ritterbach, Axel Schmolitzky, GI proceedings 105, page 33, See: <a href
 * ="http://subs.emis.de/LNI/Proceedings/Proceedings105/gi-proc-105-033.pdf">
 * http://subs.emis.de/LNI/Proceedings/Proceedings105/gi-proc-105-033.pdf</a>
 * (last visited: 18. January 2013) (only a german version is currently
 * available). (TODO Check ref, search for original GI source, search for
 * english version)</dd>
 * <dt><a name="literature2">[2]</a></dt>
 * <dd>
 * <i>Java Language Specification</i>, Third Edition, Chapter 4.2 <i>Primitive
 * Types and Values</i>, James Gosling, Bill Joy, Guy Steele and Gilad Bracha,
 * ISBN 0-321-24678-0, Online copy of this chapter available at: <a href
 * ="http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.2"
 * >http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.2</a>
 * (last visited: 18th September 2013)</dd>
 * <dt><a name="literature3">[3]</a></dt>
 * <dd>
 * <i>Java Language Specification</i>, Third Edition, Chapter 5.1.7 <i>Boxing
 * Conversion</i>, James Gosling, Bill Joy, Guy Steele and Gilad Bracha, ISBN
 * 0-321-24678-0, Online copy of this chapter available at: <a href =
 * "http://docs.oracle.com/javase/specs/jls/se5.0/html/conversions.html#5.1.7"
 * >http
 * ://docs.oracle.com/javase/specs/jls/se5.0/html/conversions.html#5.1.7</a>
 * (last visited: 18th September 2013)</dd>
 * </dl>
 * 
 * @author Matthias Zeimer
 * @version 4
 * @since 0.1, 10.01.2013
 * @param <T>
 *            The concrete value, the implementation class (auto-reflexive
 *            declaration). If the class of the subclass is {@code X} the
 *            inheritance would be declared as {@code X extends Value<X>}.
 *            Abstract subclasses must pass the type of a concrete subclass
 *            using their own type argument.
 */
public abstract class Value<T extends Value<T>> implements Cloneable,
        Comparable<T>, Serializable {

    /**
     * <p>
     * The serial version UID of this class.
     * </p>
     * 
     * @see Serializable
     */
    private static final long serialVersionUID = 509377280329392450L;

    /**
     * <p>
     * Flattens an array. All components of embedded arrays will become a
     * component of the containing arrays.
     * </p>
     * 
     * @param properties
     *            The array to flatten, not {@code null}
     * @return A copy of passed {@code properties} with flattened embedded
     *         arrays; not {@code null}
     */
    private static Object[] flattenArray(final Object[] properties) {
        final List<Object> resultAsList = new LinkedList<Object>();
        flattenArrayIteration(resultAsList, properties);
        return resultAsList.toArray();
    }

    /**
     * <p>
     * Used internally for iterations over embedded arrays by
     * {@link #flattenArray(Object[])}.
     * </p>
     * 
     * @param target
     *            The list in order of the properties array where the flattened
     *            components should be added to, not {@code null}.
     * @param properties
     *            The properties array that should be flatten, not {@code null}.
     */
    private static void flattenArrayIteration(final List<Object> target,
            final Object[] properties) {
        for (final Object eachProperty : properties) {
            if (eachProperty.getClass().isArray()) {
                // XXX Cast could be critical!
                flattenArrayIteration(target, (Object[]) eachProperty);
                continue;
            }

            target.add(eachProperty);
        }
    }

    /**
     * <p>
     * The constant {@link #hashCode()}-result of this value. This hash-code is
     * calculated overall values properties.
     * </p>
     */
    private final int hashCode;

    /**
     * <p>
     * The serialised version of this value. See description of
     * {@link #serialised()} for format details.
     * </p>
     */
    private final String serialised;

    /**
     * <p>
     * The constant {@link #toString()}-result of this value. Calculated with
     * {@link Formatter} and the format string passed to this types non-default
     * constructor.
     * </p>
     * 
     * @see #Value(String, Object...)
     */
    private final String toString;

    /**
     * <p>
     * Creates an instance during the de-serialisation process as described in
     * {@link Serializable} - <em>This constructor
     * should never be called immediately</em>.
     * </p>
     * 
     * <p>
     * This constructor is intended to be used by the JVM only. The created
     * instance is invalid and need is to be filled by the JVM with approximate
     * data. Developers may use {@link #Value(String, Object...)} to initialise
     * a value &quot;instance&quot; but <em>never</em> this constructor.
     * </p>
     * 
     * <p>
     * Sub-classes <em>must</em> initialise all fields with the default values
     * for the corresponding type within the default constructor. This should
     * underline the &quot;do not call&quot; restriction described above.
     * </p>
     */
    protected Value() {
        this.toString = null;
        this.hashCode = 0;
        this.serialised = null;
    }

    /**
     * <p>
     * Initialise a value with the specified properties and a format string for
     * producing the result of {@link #toString()}. See {@linkplain Value class
     * documentation} for restriction on allowed property-types.
     * </p>
     * 
     * @param toStringFormat
     *            A {@linkplain Formatter format string} to produce the result
     *            of {@link #toString()}. For all Date/Time formats an
     *            {@link UnmodifiableTimestamp} as corresponding property is a
     *            valid substitute for the not permitted type {@link Date}. This
     *            argument may <em>not</em> be {@code null}.
     * @param properties
     *            The properties describing this value. Passing {@code null} is
     *            interpreted as <code>new
     *            Object[] {null}</code> (an array with the length of 1 and the
     *            only element {@code null}). If this array contains native
     *            arrays as elements they are flatten. That means their
     *            components will be placed as immediate components of this
     *            array. You should only pass arrays as last element when
     *            passing properties from a sub-class because it may cause the
     *            format indices specified in format string to get invalid.
     * @throws NullPointerException
     *             if {@code toStringFormat} is {@code null}.
     * @throws IllegalFormatException
     *             If the format string contains an illegal syntax, a format
     *             specifier that is incompatible with the given arguments,
     *             insufficient arguments given the format string, or other
     *             illegal conditions to the restrictions as described for
     *             {@link Formatter}.
     * @throws NotPermittedPropertyTypeError
     *             If at least one type of a property in {@code properties} is
     *             not permitted to be used as a value property.
     */
    protected Value(final String toStringFormat, final Object... properties)
            throws NullPointerException, IllegalFormatException,
            NotPermittedPropertyTypeError {
        if (toStringFormat == null) {
            throw new NullPointerException(
                    "The argument \"toStringFormat\" may not be null.");
        }
        Object[] propertiesToWorkOn = properties;
        if (propertiesToWorkOn == null) {
            propertiesToWorkOn = new Object[] { null };
        }

        // Flatten properties array. This required if an abstract value class
        // pass properties form a concrete value beside their own as array.
        // A nice side effect of flatten is that even if we are a bit paranoid
        // we won't have to make a copy here to prevent a concurrent changes
        // between serialisation and toString generation because flatten
        // already produces a copy:
        final Object[] propertiesCopy = flattenArray(propertiesToWorkOn);

        this.serialised = SerialisationSupport.serialise(propertiesCopy)
                .intern();
        this.hashCode = this.serialised.hashCode();

        // Change unmodifiable dates to "normal" Java dates to to be used with
        // toStringFormat
        for (int index = 0; index < propertiesCopy.length; index++) {
            if (propertiesCopy[index] instanceof UnmodifiableTimestamp) {
                final UnmodifiableTimestamp unmodifiableDate = //
                UnmodifiableTimestamp.class.cast(propertiesCopy[index]);
                propertiesCopy[index] = unmodifiableDate.toDate();
            }
        }

        // FIXME discuss use of intern() -> one million values -> one million
        // strings in pool ... -> memory problem? Is pool cleared by gc()?
        // http://mindprod.com/jgloss/interned.html
        // See de.miniframes.minivalues.UnmodifiableArrayTest.testStrPool()
        this.toString = String.format(null, toStringFormat, propertiesCopy)
                .intern();
    }

    /**
     * <p>
     * Returns this value. Cloning an unmodifiable value is useless. By the fact
     * that the requirement {@code x.clone() != x} (for all {@code x
     * extends }{@link Object}) is <em>not</em> an absolute requirement this
     * implementation returns the value &quot;instance&quot; itself.
     * </p>
     * 
     * @return this.
     * @throws CloneNotSupportedException
     *             never.
     * @see Object#clone()
     */
    @Override
    public final Value<T> clone() throws CloneNotSupportedException {
        return this;
    }

    /**
     * <p>
     * Compares this value with the specified value for order. Returns a
     * negative integer, zero, or a positive integer as this value is less than,
     * equal to, or greater than the specified value.
     * </p>
     * 
     * <p>
     * This method uses {@link #calculateDifference(Value)} to determine the
     * difference of two <em>non-equal</em> values (see that methods
     * documentation to provide a custom difference calculation).
     * </p>
     * 
     * @return A negative integer, zero, or a positive integer as this value is
     *         less than, equal to, or greater than the specified value.
     * @throws ClassCastException
     *             if the other value has not exactly the same type (possible by
     *             generic type erasure).
     * @throws NullPointerException
     *             if {@code null} is passed as argument.
     * @see Comparable
     * @see #equals(Object)
     */
    @Override
    public final int compareTo(final T other) throws ClassCastException,
            NullPointerException {
        if (other == null) {
            throw new NullPointerException(
                    "The argument to compare to must not be null.");
        }

        final T otherValue = this.castToT(other);

        if (this.equals(otherValue)) {
            return 0;
        }

        final int calculatedDifference = this.calculateDifference(otherValue);
        if (calculatedDifference == 0) {
            throw new RuntimeException(
                    "Comparison result must be consistent with equals."
                            + " The method " + this.getClass().getName() + "."
                            + "calculateDifference("
                            + this.getClass().getName() + ")"
                            + " returns the invalid result value of 0."
                            + " Expected was a value describing the difference"
                            + " that need to be less or greater than 0 but"
                            + " not 0.");
        }

        return calculatedDifference;
    }

    /**
     * <p>
     * Indicates whether some other value is equal to this one.
     * </p>
     * 
     * <p>
     * Two values considered as equal if and only if:
     * <ul>
     * <li>Both have the same {@linkplain Class type},</li>
     * <li>all values properties passed to {@link #Value(String, Object...)} are
     * equal,</li>
     * <li>both hash-codes are equal and</li>
     * <li>the result of {@link #toString()} for both is equal.</li>
     * </ul>
     * </p>
     * 
     * <p>
     * All restrictions of the equivalence relation described in
     * {@link Object#equals(Object)} applies for all value types; {@code null}
     * is not a value.
     * </p>
     * 
     * @param other
     *            The object, which should be another value, with which to
     *            compare. If passing {@code null}, this method returns
     *            {@code false}.
     * @return {@code true} if and only if both values are considered as equal,
     *         {@code false} else.
     */
    @Override
    public final boolean equals(final Object other) {
        if (other == null) {
            return false;
        }

        if (this.getClass() != other.getClass()) {
            return false;
        }

        final Value<T> otherValue = this.castToT(other);

        if (this.hashCode != otherValue.hashCode) {
            // Cause the hashCode is based on the serialised version which is a
            // string, the hash-code MUST be equal for equal instances.
            return false;
        }

        return this.isToStringEquals(otherValue)
                && this.isSerialisedEquals(otherValue);
    }

    /**
     * <p>
     * Returns a hash code for this value.
     * </p>
     * 
     * <p>
     * Two equal values have the same hash code. The hash code is calculated
     * from an internal representation overall values properties passed to
     * {@link #Value(String, Object...)}.
     * </p>
     * 
     * @return The hash code for this value.
     */
    @Override
    public final int hashCode() {
        return this.hashCode;
    }

    /**
     * <p>
     * Returns the {@link String} representation of this value.
     * </p>
     * 
     * <p>
     * The returned string is the result of
     * {@link String#format(java.util.Locale, String, Object...)} using the
     * passed format string in {@link #Value(String, Object...)} and the
     * {@link Locale} set to {@code null} (without localisation).
     * </p>
     * 
     * @return This implementation never returns {@code null} but possibly an
     *         {@linkplain String#isEmpty() empty} string. Subsequent calls to
     *         the same value &quot;instance&quot; will constantly return the
     *         same string. For two equal values this method has an equal
     *         result.
     */
    @Override
    public final String toString() {
        return this.toString;
    }

    /**
     * <p>
     * Called by {@link #compareTo(Value)} to determine the difference between
     * two <em>non-equal</em> values.
     * </p>
     * 
     * <p>
     * This method is called for non-equal values only. Its calculates an
     * indicator of the difference between this and a other value. For that a
     * result of the {@code int} value {@code 0} is <em>not</em> permitted.
     * </p>
     * 
     * <p>
     * The default implementation first compares the result of
     * {@link #toString()} of this and the other value. If this does not result
     * in a difference, the result calculated from an internal representation
     * overall values properties is used, which need to be different for
     * non-equal values.
     * </p>
     * 
     * <p>
     * You may override this method for a custom difference calculation.
     * </p>
     * 
     * @param otherValue
     *            The other value to compare to, not {@code null}.
     * @return An indicator of the difference with the other value, greater or
     *         less 0 but <em>never</em> 0.
     */
    protected int calculateDifference(final T otherValue) {
        int result = this.toString.compareTo(otherValue.toString);
        if (result == 0) {
            result = this.serialised.compareTo(otherValue.serialised);
        }
        return result;
    }

    /**
     * <p>
     * The serialised version of this value.
     * </p>
     * 
     * <p>
     * <em>Note:</em> This serialisation format has mostly noting in common with
     * the serialisation format as described in {@link Serializable}. The
     * serialisation done here is a serialisation for faster equality checks and
     * for keeping a readable format in debugging sessions.
     * </p>
     * 
     * <p>
     * See {@link SerialisationSupport} for formats description.
     * </p>
     * 
     * @return The serialised version as described in
     *         {@link SerialisationSupport}. Never {@code null} and never
     *         {@linkplain String#isEmpty() empty}.
     */
    final String serialised() {
        return this.serialised;
    }

    /**
     * <p>
     * Cast an object to this value type, which is the type argument T. This
     * cast in interpreted as unsafe but must be valid through this class rules
     * described in this class documentation.
     * </p>
     * 
     * @param other
     *            The other value to cast, not {@code null}.
     * @return The argument {@code other} casted to type T, never {@code null}.
     * @throws ClassCastException
     *             if the cast failed. This could only happen if not all
     *             restriction described in this class documentation are
     *             satisfied.
     */
    @SuppressWarnings("unchecked")
    private T castToT(final Object other) throws ClassCastException {
        return (T) this.getClass().cast(other);
    }

    /**
     * <p>
     * Compares the {@linkplain #serialised() serialised version} of this value
     * with the one of the other value.
     * </p>
     * 
     * @param other
     *            The value to compare to, not {@code null}.
     * @return {@code true} if the serialised version of this value is equal to
     *         or the same as the one of the other value, {@code false} else.
     */
    private boolean isSerialisedEquals(final Value<? extends Value<?>> other) {
        if (this.serialised.intern() == other.serialised.intern()) {
            return true;
        }

        return this.serialised.equals(other.serialised);
    }

    /**
     * <p>
     * Compares the {@linkplain #toString() string representation} of this value
     * with the one of the other value.
     * </p>
     * 
     * @param other
     *            The value to compare to, not {@code null}.
     * @return {@code true} if the string representation of this value is equal
     *         to or the same as the one of the other value, {@code false} else.
     */
    private boolean isToStringEquals(final Value<? extends Value<?>> other) {
        if (this.toString.intern() == other.toString.intern()) {
            return true;
        }

        return this.toString.equals(other.toString);
    }
}
